#include "jeu.h"
#include "ennemi.h"
#include "bombe.h"

#include <stdio.h>
#include <stdlib.h>
#include "assert.h"

void jeuInit(jeu *pj, const int numeroTerrain, const int mode)
{
	marioInit(&(pj->mario),1,1);
	if (mode == 2 || mode == 3)
        marioInit(&(pj->luigi), 13, 13);
	terrainInit(&(pj->ter), numeroTerrain, mode);
}

void jeuLibere(jeu *pj)
{
	marioLibere(&(pj->mario));
	terrainLibere(&(pj->ter));
}

terrain *jeuGetTerrainPtr(jeu *pJeu)
{
	return &(pJeu->ter);
}

mario *jeuGetMarioPtr(jeu *pJeu)
{
	return &(pJeu->mario);
}

mario *jeuGetLuigiPtr(jeu *pJeu)
{
	return &(pJeu->luigi);
}

const terrain *jeuGetConstTerrainPtr(const jeu *pJeu)
{
	return &(pJeu->ter);
}

const mario *jeuGetConstMarioPtr(const jeu *pJeu)
{
	return &(pJeu->mario);
}

const mario *jeuGetConstLuigiPtr(const jeu *pJeu)
{
	return &(pJeu->luigi);
}

void jeuActionClavier(jeu *pj, const char touche, const int mode)
{
    if (mode == 1)
    {
       switch(touche)
        {
            case 'g' :
                    marioGauche(&(pj->mario), &(pj->ter));
                    break;
            case 'd' :
                    marioDroite(&(pj->mario), &(pj->ter));
                    break;
            case 'h' :
                    marioHaut(&(pj->mario), &(pj->ter));
                    break;
            case 'b' :
                    marioBas(&(pj->mario), &(pj->ter));
                    break;
            case 'a' :
                    poseBombe(&(pj->mario), &(pj->ter), 1);
                    break;
        }
    }
    else if (mode == 2)
    {
       switch(touche)
        {
            case 'g' :
                    marioGauche(&(pj->luigi), &(pj->ter));
                    break;
            case 'd' :
                    marioDroite(&(pj->luigi), &(pj->ter));
                    break;
            case 'h' :
                    marioHaut(&(pj->luigi), &(pj->ter));
                    break;
            case 'b' :
                    marioBas(&(pj->luigi), &(pj->ter));
                    break;
            case 'a' :
                    poseBombe(&(pj->luigi), &(pj->ter), 2);
                    break;
        }
    }
}

int gestionExplosion(jeu* pJeu, mario* marioM, mario* luigiL, const int mode)
{
    int i = 0;
    int vieMario = 0;
    int vieLuigi = 0;
    int continue_boucle = 1;
    int puissance = 0;
    int nbCaissesAvant = compteCaisses(&pJeu->ter);

    /* gestion de l'explosion des bombes */
    /* on récupère le temps actuel avec clock */
    pJeu->tempsBombe = clock();

    for (i = 0; i <= 6; i++)
    {
        if(pJeu->ter.bombeTab[i] != 0)
        {
            assert(pJeu->tempsBombe > 0);
            /* une bombe met 1,3 seconde à exploser */
            if (pJeu->tempsBombe - bombeGetHeureInit(pJeu->ter.bombeTab[i]) >= 1300000)
            {
                /* la portée de la bombe dépend de sa puissance */
                puissance = bombeGetPuissance(pJeu->ter.bombeTab[i]);
                vieMario = bombeExplose(&pJeu->ter, pJeu->ter.bombeTab[i], marioGetX(marioM), marioGetY(marioM));
                vieLuigi = bombeExplose(&pJeu->ter, pJeu->ter.bombeTab[i], marioGetX(luigiL), marioGetY(luigiL));

                /* mario vient de perdre une vie */
                if (vieMario == 1)
                {
                    marioM->tabBonus[0]--;
                    /* mario est mort, fin du jeu */
                    if (marioM->tabBonus[0] <= 0) {
                        continue_boucle = 0;
                    }
                }

                if (pJeu->ter.bombeTab[i]->joueur == 1)
                {
                    /* on rétablit le nombre de bombes posables en même temps */
                    marioSetBonus(marioM, 1);
                    /* mario a eu un bonus*/
                    obtientBonus(pJeu, marioM, nbCaissesAvant);
                }

                if (mode == 2 || mode == 3)
                {
                    /* luigi vient de perdre une vie */
                    if (vieLuigi == 1)
                    {
                        luigiL->tabBonus[0]--;
                        /* luigi est mort, fin du jeu */
                        if (luigiL->tabBonus[0] <= 0) {
                            continue_boucle = 0;
                        }
                    }
                    if (pJeu->ter.bombeTab[i]->joueur == 2)
                    {
                        /* on rétablit le nombre de bombes posables en même temps */
                        marioSetBonus(luigiL, 1);
                        /* luigi a eu un bonus*/
                        obtientBonus(pJeu, luigiL, nbCaissesAvant);
                    }
                }


                /* on libère la bombe */
                bombeLibere(&pJeu->ter, i);
            }
        }
     }
     return continue_boucle;
}

void deplaceEnnemis(jeu* jeu, const int mode)
{
    int i = 0;
    int luigiX, luigiY, heroX, heroY;

    int distanceAMarioX = 0;
    int distanceAMarioY = 0;
    int distanceAMario = 0;

    int distanceALuigiX = 0;
    int distanceALuigiY = 0;
    int distanceALuigi = 0;

    int marioX = marioGetX(&jeu->mario);
    int marioY = marioGetY(&jeu->mario);
    if (mode == 3)
    {
        luigiX = marioGetX(&jeu->luigi);
        luigiY = marioGetY(&jeu->luigi);
    }
    else
    {
        heroX = marioX;
        heroY = marioY;
    }
        for (i=0; i < 3; i++)
        {
            if (jeu->ter.ennemiTab[i] != 0)
            {
                if (mode == 3)
                {
                    distanceAMarioX = valeurAbs(jeu->ter.ennemiTab[i]->x - marioX);
                    distanceAMarioY = valeurAbs(jeu->ter.ennemiTab[i]->y - marioY);
                    distanceAMario = distanceAMarioX*distanceAMarioX + distanceAMarioY*distanceAMarioY;

                    distanceALuigiX = valeurAbs(jeu->ter.ennemiTab[i]->x - luigiX);
                    distanceALuigiY = valeurAbs(jeu->ter.ennemiTab[i]->y - luigiY);
                    distanceALuigi = distanceALuigiX*distanceALuigiX + distanceALuigiY*distanceALuigiY;

                    if (distanceAMario >= distanceALuigi)
                    {
                        heroX = luigiX;
                        heroY = luigiY;
                    }
                    else
                    {
                        heroX = marioX;
                        heroY = marioY;
                    }
                }
               ennemiDeplaceIA(jeu->ter.ennemiTab[i], &(jeu->ter), heroX, heroY);
               /*ennemiDeplaceAleatoirement(jeu->ter.ennemiTab[i], &(jeu->ter)); */
                ennemiAffiche(jeu->ter.ennemiTab[i],&(jeu->ter));
            }
        }
}

void obtientBonus(jeu* jeu, mario* mario, const int nbCaissesAvant)
{
    int i = 0;
    int alea = 0;
    int codeBonus;
    int nbCaissesActuel;
    int nbCaisses;

    srand(time(NULL));
    /* sélection d'un bonus aléatoire (entre 0 et 4) */
    codeBonus = rand()%5;
    /* on vérifie qu'au moins une caisse a été détruite */
    nbCaissesActuel = compteCaisses(&jeu->ter);
    nbCaisses = nbCaissesAvant - nbCaissesActuel;

    for (i=0; i < nbCaisses; i++)
    {
        alea = rand()%7;
        if (alea == 1) marioSetBonus(mario, codeBonus);
    }
}

void marioInvincible(jeu* jeu, mario* mario, const int i)
{
    jeu->tempsInvincible = time(&jeu->tempsInvincible);
    if(mario->heureInvincibilite != 0)
    {
        if (jeu->tempsInvincible - mario->heureInvincibilite >= i)
        {
            /* supprime l'invincibilité */
            marioSetBonus(mario, 5);
            /* redonne 2 vies à Mario */
            marioSetBonus(mario, 6);
        }
    }
}

int gestionDegats(jeu* jeu, mario* mario, const int i, const char direction)
{
    if (ennemiGetX(jeu->ter.ennemiTab[i]) == marioGetX(mario) &&
        ennemiGetY(jeu->ter.ennemiTab[i]) == marioGetY(mario))
    {
        mario->tabBonus[0]--;
        /* on déplace Mario de 2 pas en arrière pour lui éviter une mort assurée */
        switch (direction)
        {
            case 'h' : marioBas(mario, &jeu->ter); marioBas(mario, &jeu->ter); break;
            case 'b' : marioHaut(mario, &jeu->ter); marioHaut(mario, &jeu->ter); break;
            case 'g' : marioDroite(mario, &jeu->ter); marioDroite(mario, &jeu->ter); break;
            case 'd' : marioGauche(mario, &jeu->ter); marioGauche(mario, &jeu->ter); break;
        }

        /* Mario est mort, fin du jeu */
        if (mario->tabBonus[0] <= 0)
            return 0;
        else /* il n'est pas mort */
            return 2;
    }
    return 1;
}

int compteEnnemis (jeu* jeu)
{
    int i = 0;
    int compteur = 0;
    for (i = 0; i<4; i++)
    {
        if (jeu->ter.ennemiTab[i] != 0)
            compteur++;
    }
    return compteur;
}
